package xyz.lwm.lazycat.web.handle;

import java.nio.charset.Charset;

import static xyz.lwm.lazycat.web.handle.HttpStatus.HTTP_MOVED_TEMP;

/**
 * http context
 *
 * @author lwm
 */
public final class Context {

    private final HttpRequest req;

    private final HttpResponse res;

    private final JsonMapper json;

    // 结束标识, 若为true, HandlerChain 中后续其他 handler 也不处理
    private boolean end;

    public Context(HttpRequest req, HttpResponse res, JsonMapper json) {
        this.req = req;
        this.res = res;
        this.json = json;
    }

    public HttpRequest req() {
        return req;
    }

    public HttpResponse res() {
        return res;
    }

    public String getPath() {
        return req.getPath();
    }

    public String getHeader(String headerKey) {
        return req.getHeader(headerKey);
    }

    public String getParam(String name) {
        return req.getParam(name);
    }

    public <T> T bodyAsClass(Class<T> clz) {
        return json.fromJsonBytes(req.getBodyBytes(), clz);
    }

    public void setCharset(Charset charset) {
        res.setCharset(charset);
    }

    public void setHeader(String header, String value) {
        res.setHeader(header, value);
    }

    public void sendOk() {
        send(HttpStatus.HTTP_OK);
    }

    public void send(int httpStatusCode) {
        res.setStatus(httpStatusCode);
    }

    public boolean isSent() {
        return res.hasSetStatus();
    }

    public void write(String data) {
        res.write(data);
    }

    public void sendError(int errorCode, String content) {
        res.setStatus(errorCode);
        res.setContentType(ContentType.TEXT_HTML.toString());
        res.write(content);
    }

    public void json(Object obj) {
        res.setContentType("application/json");
        res.write(json.toJsonBytes(obj));
    }

    public void redirect(String url) {
        setHeader(Header.LOCATION.getValue(), url);
        res.setStatus(HTTP_MOVED_TEMP, -1);
    }

    // 结束 context 操作, 后续 handler 不再处理
    public void end() {
        this.end = true;
    }

    // 判断 context 是否结束
    boolean ended() {
        return end;
    }

}
